/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2015 - 2018 Red Hat, Inc.
 */

#include "src/core/nm-default-daemon.h"

#include <linux/rtnetlink.h>

#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nm-linux-platform.h"

#include "nm-test-utils-core.h"

/*****************************************************************************/

G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr)
                == G_STRUCT_OFFSET(NMPlatformIP4Address, address));
G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPAddress, address_ptr)
                == G_STRUCT_OFFSET(NMPlatformIP6Address, address));

G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr)
                == G_STRUCT_OFFSET(NMPlatformIP4Route, network));
G_STATIC_ASSERT(G_STRUCT_OFFSET(NMPlatformIPRoute, network_ptr)
                == G_STRUCT_OFFSET(NMPlatformIP6Route, network));

/*****************************************************************************/

static void
test_init_linux_platform(void)
{
    gs_unref_object NMPlatform *platform = NULL;

    platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT);
}

/*****************************************************************************/

static void
test_link_get_all(void)
{
    gs_unref_object NMPlatform *platform = NULL;
    gs_unref_ptrarray GPtrArray *links   = NULL;

    platform = nm_linux_platform_new(TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT);

    links = nm_platform_link_get_all(platform, TRUE);
}

/*****************************************************************************/

static void
test_nm_platform_link_flags2str(void)
{
    int i;

    for (i = 0; i < 100; i++) {
        char        buf[NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN + 100];
        const char *s;
        const guint flags = ((i == 0) ? ~0u : nmtst_get_rand_uint());
        gsize       l;

        s = nm_platform_link_flags2str(flags, buf, sizeof(buf));
        g_assert(s);

        l = strlen(s);
        if (l > NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN)
            g_error(
                "nm_platform_link_flags2str(%x) produced a longer output than %zu chars: \"%s\"",
                flags,
                NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN,
                s);
        if (flags == ~0u && l != NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN)
            g_error("nm_platform_link_flags2str(%x) is expected to produce %zu chars, but produced "
                    "%zu: \"%s\"",
                    flags,
                    NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN,
                    l,
                    s);
    }
}

/*****************************************************************************/

static int
_address_pretty_sort_cmp(gconstpointer a, gconstpointer b, gpointer test_data)
{
    const int                   TEST_DATA_I      = GPOINTER_TO_INT(test_data);
    const int                   addr_family      = (TEST_DATA_I == 0 ? AF_INET : AF_INET6);
    const int                   IPV6_PREFER_TEMP = (TEST_DATA_I == 2);
    const NMPlatformIPXAddress *a_a              = a;
    const NMPlatformIPXAddress *a_b              = b;

    if (addr_family == AF_INET)
        return nm_platform_ip4_address_pretty_sort_cmp(&a_a->a4, &a_b->a4);

    return nm_platform_ip6_address_pretty_sort_cmp(&a_a->a6, &a_b->a6, IPV6_PREFER_TEMP);
}

static void
test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data)
{
    static const char *const EXPECTED_BUFFER[3] = {
        [0] = ("5b1aea34648cabfec7c3523f76cf1ce34ca17a9a32f3f0f218424e48836dd1cb504e03d53e1124c5"
               "0065aeb2e6fbf952902383028e3b47f280f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a"
               "8982c42f0000003437c5156e072b2f2f0037c9cfe07c34ddb3980deb14ab7b5af84a034703000000"
               "883b0f3fd6ed84d6c959e553b887edcd01c2f5d200000043b809d259e499db7d00f1853bdcb0e4bc"
               "0e2b00b667b7b16d8d1e69c803000000b973972c17a47631c169f11ff9119c400368b6630000007a"
               "034f43340d01683c0045097aea4a849f060ddf57b24a5be9636360d603000000ad7c499dd538d345"
               "74c038404923e75d0209e2fc0000004acc807cdce682f80f00315c45ef817264c89a736ed55ed637"
               "b96c200203000000faf1809becd2506315a6da29b2e94d3a031fe0e900000083a36035fb6297dfa7"
               "00686b5efd0d53bb6215de4bb6f6f3d031a79028030000008bb836c0a25ea71f5daaed4d99eb2ebe"
               "033c432f000000bf4ccf30d3aaaf02a4005d7308b67f91bf9d82c856ba942455e8d07c8403000000"
               "f2abb982b001ec16901f55f960c55c22022099a80000002b4d4647f53b1921af0088e3759a08e7a5"
               "6663861eea1bf42c12ea3b9503000000fb95e8332fdfff658483a2d039a7bf1402d3481e00000060"
               "e89f7abdb682380a00eae374835b4a49a2b980b6aba92da6409969aa03000000e00473755d31e5b2"
               "de252167c1c91b3a02ba0c700000007740318db913a353ed006efc068829c0e66ad0143a0554efb4"
               "40e55b8b03000000c0cfb2b4386bec092fa5757ecde9348b00c12ebd000000ab667224dae775e5cc"
               "0041aca2ff0f576767d3648102b61886d149f07403000000153ece68ade15cec25a59273e7519f34"
               "c4458d70000000f3819aa46fbe1439340033ae6dec0fb124f264af67eed7c9a8ecc8fb1103000000"
               "fcebbaeb0c56535923f14874042a8aff021f8e5ec3cc13cc36bbe3c9bb0ec36f00e007bb64a2827b"
               "7cdd38d0314c178e5a06c40b03000000ab90135fa636af4464d210a256be75e0029c44770000004b"
               "2e69220d6c0fc09c25d6534c809829af4a9df58dbfef186d416f3a1e030000002c932e655203d82a"
               "3c84c4eb274ed18603780281000000f2235376239daeaacb3cae864b437baaae91921681c2162b9b"
               "69e66142030000004fda8a3e0b841cf76391dd68269b53ec0244a831000000b78c54dda9ac3bb1b1"
               "d43e6505621b9a7f0422ae3fc8979ee0416f95e70300000057d6249b652ba98c7dc7f17f666969e4"
               "023baf7a000000ee0b06fa9e988f80f0de6dc8dfcf2a3ad3bbcc0fa3b314f695111d891d03000000"
               "cd897619f51f44e644d7cf1d06b2b1150082549e62c12fba5b1cdec48d10bbb13b8313d8cd2a24d3"
               "4fc812bd2f8a59d90fcc00ac030000005292cd32dc096cd5d8a4c5cf3351ee1c03c2056c00000051"
               "bbce426cfa4b861cc78592be7b14e7ba9c15acb881ae55f0e5fe7d360300000066a3ae3939762df3"
               "3a2d55060c78d55100b110fd00000041b9aca07b6e4925dd27943a272c171ed15abbbe1cd911db7b"
               "86ed271803000000a5edc511c1507a141e0f515638c7ba31027609450000003357ae79989870ccec"
               "3def0ad92749e016663fe6ee0228c1da82d1595603000000348352d715cf9d411ea012e5307294b6"
               "0146dac4000000075efee38dd16f8ee4ccd2f50c30706cae3fdcc2f0ee3d5e26bb20413203000000"
               "862573c2303dd1d65c7b2cffeca6d1adaccae11f0000000f855ebf3b772eb2b1c896c9a7304f6645"
               "0a5f6abd850b06e3b10123e6030000001dff045298cfee0636674cdefb57b9ae54cfe8f400000038"
               "1ba2c4396de60f032bc7f34de2959871c0d4c0d4eb720c4ab550c5db03000000f32f4af595d785d5"
               "c1b5aad487c192f08bd7a09b00000043288cd9bf66ec305a225a0c71b2ce78bb16104c8eaf18c565"
               "b16c7376030000005219061ab4c5c79489b2cc6a883c146972decb8b000000f5e6d66df46ea13910"
               "7754dee62c36d2fc70ccc567df7a49b8585287dc03000000cfb18b2b2cb749e2e03e544d0eb4f73e"
               "75039fcf251b32fc79685b05ddd3aa9ba511d2e40edb4d758fb554158ae5c7c0beb42b3403000000"
               "895d5f24037d233302ad3b82d639272e0246eadfbd2146bf8cfdb205f90e54b58a6ee136a779f37c"
               "30d2c5053c40ecaec38b6b8e03000000bea73223e59bf0193432e9fa7a899f2d8ec7e4b89bf5a5d0"
               "6776e66a9d80ab132e1ac921eb76adbb229df32e561fa80a0fc4676703000000a23eb66e720da9e0"
               "7ac998b5690807d50217369ee1af4ca5a6a95581af5fd7ceacdca10f47d7b351a36b178aabc78a4a"
               "1a0dd8c003000000e2815a1a37a52bddd1c2f1018b587eed03bb58f0e9201f17bd99fcf72909ac9e"
               "7a55299e9bb4fd53bc7417940fcffe3f81cafd6302000000d6732578acd14320aefd4503189f7630"
               "038e501c0000002b9f3c39f24b0572b100745cb25851429b3bbfb50168dfd04eb62f22ca02000000"
               "891715df7fc6a902edae579e2e10c7f7022ba0340436242cbeb0248cee3fbc160032d4f28aa28c08"
               "f80dd50c6712dfb4abba4a32020000008ffe423d01883918039249f398f9b37ea091465100000064"
               "3722d9b707c0d8a400b7c8307f06b4b29088f20d9ac676d5e4bafc4e02000000fde69eec3af2e6d0"
               "bd68ab722af14548b29572e504265f6c72923e22594f3f790008ed2e2ebb0771db46a54cadb245ea"
               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd6011fa56dfdcfc1155f236c8b9c79a620"
               "00660bbf024b03ff0a8e27c405e64244e36f90d402000000fd41fe47684b370b6ec6584d64496089"
               "570968ead4d1ae91c819bb068196d59900de3246e43f5e7945aaf95e2ffa3a119c64ed0402000000"
               "a660ac824b7fae389861419c50da49bf02092583000000259f9f0251becc987907879cca68fec7bb"
               "bb5f8edf248b4995d184e82002000000a19cdf6dd1c173f6078a806d329c9b0000bfc972000000f5"
               "b2cd3dbddc74e26de958e48d2ab8b0313e7f8933e315130f641e447502000000b9b68c08a5e4351e"
               "a349e1ccf662e058b879a45100000045fcb6a035339d504c9726d80d9c2d89df765b4d9a130257dc"
               "d1e1b34902000000bcd7be07d78e6222e45aaf61814f703b40125e6b000000cbaaa37b861e6d46da"
               "fe7d6ec4ac1ea051010911915ddb05f2c43bd794010000005bfe47c6f53a54e01b0c1d89414d94d0"
               "032d2ec50000000103781b0f294a2b7300421398f4de67e9cee64b38b56e03e01539ce4101000000"
               "18238487a417f3da01d99dae5f19009601582cab0000005b2363d13edc5aa115005eb914d8fbe9a4"
               "fdb3d117d76b0de5bd82e9ea010000003d1b91caae8cb60b49ba9be338d856a40267c3d400000064"
               "9da90bd2fff2f2560046870bd7d5f14870c6d18d6242b356b9ef1b2101000000f90adac616a31dc2"
               "e46a234558817151008fc9c900000073e64b0bd761fdf274005dca8ce1bd1871ae17bb4515856092"
               "b4d9e89b010000006855676c277cf1bd017c9148da5892bb0351c3a70000009f3391ce7d3fd48469"
               "005f0c233dbdd2a97835df1f1782dee86c1de913010000003ee1d76fc1ea76e98c9dfc78997ab53e"
               "00c21963f5b4cb2454830c68e44ea74b002b83f9b3bee14d861a4c9eeecc89f65408c1b701000000"
               "d9e1825fa638e1af284a024b7f9e85ff00e050a2000000276e08cb887464b93400c3127c750fabdd"
               "69121aec129cdc690d58fbcc01000000d0d44ff1e51c35157666c05348e6f50700a8e89800000012"
               "b900b2061d0c334b009f2dd1cdf64b0f9a60e0e289f08db3fde6b0250100000039dd8f88152a5845"
               "4d9ca9d20f45dfa702e78604000000fbcd7db68b9ae586da00b4070c50320427c4dd3d031e33f22c"
               "210aeb09010000007000b96d06992b6a58acd3995b9663d20248f333ef467092818aa77d6732b678"
               "00844ef5a943825fcd743f59bd14c89b955e1a13010000007acbce3e3bcdf3824f1b134847ff26ba"
               "009a774900000017ec852d59f3d17232edd86ad6c3103a68843a9aef34983882d3d3878501000000"
               "5e0dfe491d1ba96742c7b5e02b2271220188b02a06d0dc5504b0595daf37deb499996bfb667f072d"
               "ec1e5d9cdc8a11f4409bcfb30100000099d90a8543961b2ccd47724a3c460ba80383f4c500000063"
               "eafb1ac4c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8ca0100000027335a25a364d101"
               "5ffac03089f4553902b01784000000d7b83579b8da27345a72437f9b6245de39ec9e71ee4b951507"
               "f121014a01000000efc67bce716c856e3973dc42a1003be94f89d8ee0000009b5d5bbe6c10085f3d"
               "6176f78a19bb8df1804c122fce5078c156e8f3fe010000000ea8042602a1f8e6f5657f3f9e3eb807"
               "cbad7645000000b8df6f628a70456d79f25d5895fb57fa60d9279fb2b8fcbac65ad47b8a01000000"
               "da40d88d40a6d75bc404156225b7eedefc2b44574b15e2ae496ad01bf007eacb0a28aec868282510"
               "b60291ea6480e356925b568a0000000087bb24e5264fd3ebe9cf9f6df9615189018ee815000000a7"
               "5c9555876b6a3f13002b6cb8360feaac1d5c302df59dd32a7a859db500000000362956cd46646a0e"
               "222160e5f769bb290366ed370000005b6a813387e99bb834009da86c64fefab2548759d313a5b92d"
               "8e47935e0000000034f0386a253c21d94064f6b021281e230094ae20000000d71fd050bf8d85055b"
               "00e3756ccdb3455c60ca7b11c66af76e594f24a100000000e143fd52599364e13468f80fd514573f"
               "b572671c0000006932d1d5f5d0ce2cf6007a70ba5193a162bc92ec1b11d9172c857ae81200000000"
               "3e29535402e9b690c628d048eacce745ea213cb1000000b632ef3be6070dafa200187470e9da5570"
               "9427c226d324d9a08487fd0d00000000b7a350f9fc1519defa7db4532545666937c22a3b000000dc"
               "c405cbee5016c25200d8901d7a0165fe20744edb6ba04f14a4c73cf500000000a4bab14874afdf54"
               "e6aae816430607ca0675e09818e9bbec5918c59068baf76a008940f6fc3bbdc7f6090f756aae660b"
               "6e4c699300000000d9c1e67743efb54e54270e46042e911803894e38000000376feecb80ac245409"
               "c0becc271d9c2f67179bff0644399ae7e3c9472e00000000c5cfd9f2343b21362c19a0921dce2f83"
               "00defa45000000270b9977e166bee737fe73670c439a644c323b59b4cd20eb7dabea74f700000000"
               "f6989d2d6a909e986ff7add5df2c93e05459507b0000000f466554d2ae4d52a8c67b2e48b47003c8"
               "1785d3ffdbd9a617df6b3542000000004c5cf8107ba282f4f983821918f93e742d08f0550000006f"
               "2292362e5d68265d9f98c82d9b7a559be3acf4fc36fa6b5159747cf200000000ab2dadc5a39411fd"
               "4ff1116d478987316a553fc2000000cfc6ebe434a7ae8ff040483e310819e3b10db116431ec6f769"
               "438a72e1000000002495a609675344f7e2e3a5ebaec3c85f0a1742f70abe95c50345132a61eda239"
               "d9d083c3bf085387046ef8a36f0e9e696b382ab0000000009a6ce5d906837dbca6a5ee19d6f63fe9"
               "03dd01f7246f13b2050424a2b3a45ef7a029c896b4132bd895072cfeffe9d6815997069500000000"
               "0d3c723b91adb0da7c4aa7e7eb5a15bc03015fb98b841fd84cc43c510385b9a4c2aac1d67a909b29"
               "7c703915312e9c3cae02dfa000000000dd603bd35e7fa0f02f2f3313d8469d09a92409c0b7f0318a"
               "575a4f8e061db3dd7fde25654a4059d565dbc8a91e3b4457b077ddad3108be69f9b97d05c917ad6b"
               "10e693bb6e26f2ba90c8e909a9fe20e5c7a4c656482a9b0d00625009a40aeb62a42b6a62548e3c38"
               "cd3c72f203000000ca82ac5180101be4f85cef468ea086ea01aafdc3a9fe1ec787bc45db7c52a52d"
               "00bd39a44e8e8bc17c01ac63eca0c1cf5ff7f03a03000000c9a89192c1c8be55281a59d1fd338f35"
               "0075f8cea9fec34573654ea6624f138ef9531cd9367a02e4d241989477a363d53b02239e03000000"
               "24438387def0f4c6544e4b275d9b714600f810d2a9fec17647176b7c07d856e3b883efebc09dd9d6"
               "1966b7ae7412041d57393c6f03000000182c0287822a272bec4501a1e27acfee018588ffa9fe6cae"
               "426de59560fad65d67c624f285d7174177a47579dda0b6eaa9a84c820300000070b1646d8026e9f1"
               "704f1b16286ba2da017ef082a9feed33ef60a8b540b26f66761d1f13badfad0fe8fa8f3c1aad2a82"
               "fa40546c03000000df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea9fe3e7d75a2f42b50c6a363"
               "40132378b95c59313bacba64dbe996206e6904f50200000047150b9b14010469823acb72bb89182f"
               "00112196a9feb9153b36bc60be5b534e006527f67485ab35aca0c7ee419733853cf09e8b02000000"
               "e79c10acfce165e332a62384ec04e5ba009185ada9fe0070a36dd51323b2c54200154d12f86c260a"
               "9edfa7a74c1c83c1050f63f802000000443cacf59c6379a44b7892f487afa98c0221c19ca9fe942f"
               "460bcea75481f25e007d0de9a7afe283bd2f22ead05ff72006c83bc0020000004bdade862c224f6f"
               "36506ebd455e679c00369bb8a9fecec3f8c8fa6867a982be8a934f852cc3d4d82bc0ec7303f99f8f"
               "def85b7502000000a0bef8675b29a197b7b3cceaf5f1bb120335256aa9fe6e5d58099ffc4a503a71"
               "2350acbd48411f0dc15d2f0f49dad345d966279502000000e06302aba042aaa218dc091e9aa1477f"
               "6fdc9830a9fec95829a8838314dff34d24c332219a1b163a732d803e0e2f4f916d06412601000000"
               "98c39e7cc282208fefc57ff447036b9501adcb22a9fe793f797a3c7dadd1c86e009d0c90bc512e13"
               "7dcef5e4a27985bd5cfd5ce601000000152f2b70eaef7443e0f79ab6902dde5301b3ec71a9fe9f25"
               "4ac95883195580410062ed564153e17478f8c3344d89c0bbfaa100fd01000000be184524a6bdc878"
               "9cf851782d895bcc03a98489a9fe8c1287e6f7bb020ffdb00012098610e52bb2a16a4008aefd545b"
               "0d80684e01000000ba8110fb9733cc24904f288262e6ea77032fa5f8a9feeefa701d120523bd98f2"
               "00098b43cd68be6e3f81268193fd637e9037d7a701000000c47cf0f551e96770a754ac19ef820fe0"
               "0031f2d3a9fe049150b8d10ab700cc3a7cf51be0403b654ba2f56808092069af5f5b481b01000000"
               "68cb3bc873b04d937a6ed8f7bc51e54066fed098a9fe048a92d3adc69a84eb47622400207799416a"
               "f1f0a086fbd7e2f7dea0077a00000000c386e9c6e6a2cbfa10ee58bdc75183600085d627a9feb1cb"
               "e491cbbbf9443fd6007eb3c5bf64b671d6f18dbf463f9b83f512dc1c00000000fbab244735d67c61"
               "283031667b2d74a102e0b1b1a9fe2aa590a2312e17f1a35900459582f4ef43c780908872746e39ef"
               "a9a89f8700000000fcdf6d9be94030b34774d1d7dddedd9802f0f627a9fe965a87041331b2834bcf"
               "00b4e3ce848518c4e3f6cbf25e5e1b992231bb0200000000173c333cd03bc905b7b899afeb760e3f"
               "024a2efca9fe96b89b1bc8f415bd4e77be46bae5a1b3cae76665a268abfe8a41a84e27c100000000"
               "cb29efdf672d2fa57fc85ebbe276c5660364192da9fee7af5eb888e9eb37bb046686943b101e1f55"
               "3215abf8fbdf17c3677e5a3a00000000608df061d45d864d09f4ecf17625f82d03c74828a9fe1e37"
               "1051852c972ea7954079884af257b044fd13a6826a4c619f3d136cac000000009402a4c216772167"
               "3f2b02b3256ead1f03ea9bc1a9fefca162fb81e733cff620ca7feefe1933631e8e69f6d9d6962d2c"),
        [1] = ("54270e46020000006a894e387625da376feecb80ac245409c0becc271d9c2f67179bff0644399ae7"
               "9c64ed0432d599eaa660ac824b7fae389861419c7a899f2d010000009bf5a5d06776e66a9d80ab13"
               "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b"
               "c4e1966800000000b3121cd5ef51e696c816290dbaee0e7726d082e1530ff5397c9125f59577d71c"
               "4b258a005116d11354edff62ceaa458fc75a91c425a5927300000000c4458d70911714f1819aa46f"
               "be143934c933ae6dec0fb124f264af67eed7c9a8c38b6b8ee2614344bea73223e59bf0193432e9fa"
               "4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44"
               "64d210a256be75e0509c4477d19ac64b2e69220d12ea3b9501000000fb95e8332fdfff658483a2d0"
               "39a7bf148ed3481e0bccc460e89f7abdb682380a62eae374835b4a49a2b980b6aba92da6409969aa"
               "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359"
               "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9bb0ec36f0000000064a2827b7cdd38d0314c178e"
               "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13"
               "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226"
               "d324d9a086ed27184b443181a5edc511c1507a142fea9bc10300000062fb81e733cff620ca7feefe"
               "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196"
               "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911"
               "4bdade862c224f6f36506ebd455e679cef369bb8d514573f03000000f6932f6932d1d5f5d0ce2cf6"
               "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd"
               "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d"
               "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a41e0f515601000000f57609453df7803357ae7998"
               "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7"
               "ae8cb60b0300000038d856a40c67c3d4afa9c8649da90bd2fff2f256000000000000000000000000"
               "00000001955e1a13d1111b067acbce3e3bcdf38200154d12010000009edfa7a74c1c83c18e47935e"
               "8354846e34f0386a00000000000000000000000000000001ac26c7d41fd050bf8d85055bcfe3756c"
               "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000"
               "00000000020ffdb0e612098610e52bb2a16a40086f0e9e6903000000ec2e2924348352d715cf9d41"
               "1ea012e5307294b600000000000000000000000000000000ccd2f50c30706cae3fdcc2f0ee3d5e26"
               "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000"
               "0000000000459582f4ef43c780908872746e39efaefd545b020000007ced4f8b362956cd46646a0e"
               "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d"
               "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000"
               "0000000069d9942f460bcea75481f25e307d0de96e91b91501000000be5b534e0a6527f67485ab35"
               "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b"
               "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000"
               "00000000b49185ad9b7d0070a36dd51323b2c542e5fe7d360100000066a3ae3939762df33a2d5506"
               "0c78d551cbb110fd000000000000000000000000000000002c171ed15abbbe1cd911db7b56e8f3fe"
               "9a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7246f13b2050424a2000000000000000000000000"
               "00000000ffe9d6812231bb02f922259b173c333cbae87d60000000005d31e5b2de252167c1c91b3a"
               "36ba0c700ee78477000000000000000000000000000000006ad0143a0554efb46b382ab0404cdf02"
               "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000"
               "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8"
               "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec"
               "7666c05303000000ffa8e89871fb9510b900b2061d0c334b819f2dd1000000000000000000000000"
               "00000000095a3230fde69eec3af2e6d0bd68ab7210613fc90200000016a31dc2e46a234558817151"
               "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2"
               "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000"
               "00000000b314f695bd82e9ea8891ed0a3d1b91cab56e03e0010000002f70249eefc67bce716c856e"
               "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1"
               "eecc89f601000000d635edea8ffe423d01883918039249f398f9b37e000000000000000000000000"
               "000000001fb7c8307f06b4b29088f20d9ac676d5f90e54b501000000a779f37c30d2c5053c40ecae"
               "210aeb0934cb2a2400000000000000000000000000000000df48f333ef467092818aa77d6732b678"
               "bcd7be0700000000e45aaf61814f703b40125e6baf4648cbaaa37b86000000000000000000000000"
               "000000005ddb05f2a84e27c18a06e2c9cb29efdf50da49bf00000000d94beb259f9f0251becc9879"
               "07879cca68fec7bb000000000000000000000000000000009402a4c2167721673f2b02b3256ead1f"
               "a349e1cc00000000b879a45176740744fcb6a035339d504c9726d80d000000000000000000000000"
               "000000009518862bc9a89192c1c8be55281a59d1ebfdcec30000000067a982be8a934f852cc3d4d8"
               "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a"
               "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000"
               "00000002e6fbf952902383028e3b47f2111d891d536c75bb01000000720da9e07ac998b5690807d5"
               "2617369ee1af4ca500000000000000000000ffff47d7b351a36b178aabc78a4a0d80684ee5dbf45b"
               "17a4763102000000f9119c40b468b66331bca67a034f43340d01683c00000000000000000000ffff"
               "b24a5be9b10123e6e4f15ecd1dff045298cfee069c88b02a0300000004b0595daf37deb499996bfb"
               "667f072dec1e5d9cdc8a11f4409bcfb3c167090e99d90a8543961b2ccd47724a3c460ba85183f4c5"
               "a7afe28302000000d05ff720b16c73761a3fcb675219061ab4c5c79489b2cc6a883c146972decb8b"
               "5adac8f5e6d66df46ea139107754dee62c36d2fcc7a4c65601000000cd625009a40aeb62a42b6a62"
               "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb"
               "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599"
               "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b21cdb3455c00000000c66af76e80f062ea1a7e0b7b"
               "e218d067530e1b0487b8c3b99f2b8a1a8982c42f53700a3437c5156e072b2f2fb337c9cfe07c34dd"
               "c896c9a7000000000a5f6abd850b06e3d9662795ce2cc1cee06302aba042aaa218dc091e9aa1477f"
               "6fdc9830d7fbc95829a8838314dff34d24c332214d4647f5000000000f88e3759a08e7a56663861e"
               "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db"
               "7625ca4a00000000e682f80f94315c45ef817264c89a736ed55ed637b077ddad3108be69f9b97d05"
               "c917ad6b10e693bb6e26f2ba90c8e909e85e20e5b0916e5d030000004a503a712350acbd48411f0d"
               "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8"
               "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e"
               "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c"
               "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378"
               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620"
               "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2"
               "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034"
               "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9"
               "4d88189c471a1ff2f0ce3ff66e782110125ae2eddaae7d6300000000c0982b283aa9986700b2a2b3"
               "ed257b8b0489f48f053ec8cac72105b327335a25a364d1015ffac03089f45539e1b0178462156cd6"
               "6855676c00000000017c9148da5892bb4951c3a7ed55689d3391ce7d3fd48469845f0c233dbdd2a9"
               "7835df1f1782dee88487fd0db5971b46b7a350f998c39e7c00000000efc57ff447036b9551adcb22"
               "fd50793f797a3c7dadd1c86e759d0c90bc512e137dcef5e4a27985bd8d1e69c83dc21056b973972c"
               "bc51e540030000006c3d048a92d3adc69a84eb47622400207799416afef0a086fbd7e2f7dea0077a"
               "e9c0c0d9c386e9c6e6a2cbfa10ee58bdc75183600422ae3f03000000c43bd794c697895e5bfe47c6"
               "f53a54e01b0c1d89fecd94d0e02d2ec587fc330003781b0f294a2b73c4421398f4de67e9cee64b38"
               "69121aec010000000fcc00ac2daa755e5292cd32dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51"
               "bbce426cfa4b861cc78592be7b14e7ba9c15acb836674cde0200000054cfe8f42bf0e9381ba2c439"
               "6de60f032bc7f34dfe959871c0d4c0d4eb720c4ae3c9472e5f2da5d9c5cfd9f2343b21362c19a092"
               "b2cd3dbd01000000e958e48d2ab8b0313e7f8933e315130fa9a84c82feb83f6e70b1646d8026e9f1"
               "704f1b16286ba2dabc7ef0820c91ed33ef60a8b5bcfe97e1000000007ad742d3d7320a4f880cf47f"
               "5dd0cf69cb22840ffeb3fe7749509cb6752b2cee30b7e7736a0afc9879ea40e69710fc9f6e8e99cd"
               "1dce2f83020000003a3efc240b9977e166bee737fe73670c439a644c000000000000000000000000"
               "000000015e0dfe491d1ba96742c7b5e02b227122cf844ef501000000cd743f59bd14c89b5cfd5ce6"
               "e82e7854152f2b700000000000000000000000000000000127e19f254ac9588319558041fc62ed56"
               "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000"
               "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f"
               "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e"
               "0436242c03000000ee3fbc164632d4f28aa28c08f80dd50c6712dfb4000000000000000000000000"
               "00000000078a806d329c9b008bbfc9723107f3f52af145480300000004265f6c72923e22594f3f79"
               "e208ed2e2ebb07710000000000000000000000000000000039dd8f88152a58454d9ca9d20f45dfa7"
               "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000"
               "000000008ae21e371051852c972ea7954079884a9a1b163a030000000e2f4f911a0dd8c052ed6b13"
               "e2815a1a37a52bdd00000000000000000000000000000000bd99fcf72909ac9e7a55299e9bb4fd53"
               "9f3c2c8803000000f51f44e644d7cf1d06b2b115d882549e62c12fba000000000000000000000000"
               "000000004fc812bd2f8a59d96d064126666befbbf257b044030000006a4c619f9037d7a754655354"
               "c47cf0f551e967700000000000000000000000000000000050b8d10ab700cc3a7cf51be0403b654b"
               "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000"
               "00000000d538d34574c038404923e75d0e09e2fcfc1519de010000002545666937c22a3b6e9686dc"
               "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e"
               "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000"
               "00000000b883efebc09dd9d61966b7ae7412041dd7ac5f9901000000822a272bec4501a1e27acfee"
               "7a8588ffd5a06cae0000000000000000000000000000000077a47579dda0b6ead1e1b34901eaedd5"
               "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000"
               "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096"
               "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f"
               "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000"
               "000000005b29a197b7b3cceaf5f1bb12c535256a74993ade03000000e62112898dab2dade2ab2fc9"
               "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8"
               "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000"
               "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050"
               "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f"
               "bc74179403000000438a72e12ae0436a2495a609675344f7e2e3a5eb000000000000000000000000"
               "0000000061eda239d9d083c3bf085387046ef8a34153e174020000004d89c0bb5408c1b7d17fb084"
               "d9e1825fa638e1af000000000000000000000000000000006e08cb887464b9344ec3127c750fabdd"
               "6c0fc09c02000000809829af4a9df58dbfef186d416f3a1ef170d10f000000000000000000000000"
               "0000000087780281d47a32f2235376239daeaacba9a89f8701000000fcdf6d9be94030b34774d1d7"
               "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767"
               "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000"
               "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc"
               "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515"
               "b7f0318a01000000061db3dd7fde25654a4059d565dbc8a91e3b4457000000000000000000000000"
               "00000000c1b5aad487c192f08bd7a09bdd21444359747cf200000000ab2dadc5a39411fd4ff1116d"
               "478987316a553fc2000000000000000000000000000000000819e3b10db116431ec6f7691539ce41"
               "b95c593100000000dbe9962069e66142e22753344fda8a3e0b841cf7000000000000000000000000"
               "000000008c54dda9ac3bb1b1d43e6505621b9a7f672d2fa501000000e276c5661a64192db44ce7af"
               "5eb888e9eb37bb0400000000000000000000000000000002641e447514ca565fb9b68c08a5e4351e"
               "9f3c39f201000000de745cb25851429b3bbfb50168dfd04edf6b3542000000000000000000000000"
               "0000000218f93e742d08f0550b55726f2292362e70ccc56700000000a4c73cf5ffa4ffc8a4bab148"
               "74afdf54e6aae8160000000000000000000000000000000268baf76ab08940f6fc3bbdc7f6090f75"
               "4f1b134803000000449a774929e86716ec852d59f3d17232edd86ad6000000000000000000000000"
               "000000027dba1ee7e143fd52599364e13468f80f40b26f6603000000badfad0fe8fa8f3c1aad2a82"
               "530b7447d9c2f401000000000000000000000000000000028147507e1cd59ea1ae6da48b1eba6d16"
               "dedea2030100000002a1f8e6f5657f3f9e3eb807cbad76451055edb8000000000000000000000000"
               "00000002d9279fb2b8fcbac6abea74f7a6df7979f6989d2d000000006ff7add5df2c93e05459507b"
               "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"),
        [2] = ("4cc43c5103000000c2aac1d67a909b297c703915312e9c3c5a06c40b20ea99d5ab90135fa636af44"
               "64d210a256be75e0509c4477d19ac64b2e69220d54270e46020000006a894e387625da376feecb80"
               "ac245409c0becc271d9c2f67179bff0644399ae79c64ed0432d599eaa660ac824b7fae389861419c"
               "12ea3b9501000000fb95e8332fdfff658483a2d039a7bf148ed3481e0bccc460e89f7abdb682380a"
               "62eae374835b4a49a2b980b6aba92da6409969aa7a899f2d010000009bf5a5d06776e66a9d80ab13"
               "2e1ac921eb76adbb229df32e561fa80a40e55b8b1dd92e18c0cfb2b4386bec092fa5757ecde9348b"
               "288cd9bf00000000225a0c71b2ce78bb16104c8eaf18c565ecc8fb112087b97cfcebbaeb0c565359"
               "23f14874042a8aff1d1f8e5ec3cc13cc36bbe3c9c4e1966800000000b3121cd5ef51e696c816290d"
               "baee0e7726d082e1530ff5397c9125f59577d71c4b258a005116d11354edff62ceaa458fc75a91c4"
               "25a5927300000000c4458d70911714f1819aa46fbe143934c933ae6dec0fb124f264af67eed7c9a8"
               "c38b6b8ee2614344bea73223e59bf0193432e9fa2fea9bc10300000062fb81e733cff620ca7feefe"
               "1933631e8e69f6d9fed62d2c6e6904f57239c09c47150b9b14010469823acb72bb89182f93112196"
               "9985d62700000000e491cbbbf9443fd6a77eb3c5bf64b671d6f18dbffeff9b8306c83bc026977911"
               "4bdade862c224f6f36506ebd455e679cef369bb8bb0ec36f0000000064a2827b7cdd38d0314c178e"
               "925b568ae56bc4e9fefb24e5264fd3ebe9cf9f6df9615189f78ee815b2781ea55c9555876b6a3f13"
               "02e9b69000000000eacce745ea213cb1a84035b632ef3be6070dafa2fed87470e9da55709427c226"
               "d324d9a086ed27184b443181a5edc511c1507a14d514573f03000000f6932f6932d1d5f5d0ce2cf6"
               "bf7a70ba5193a162fe92ec1b11d9172cf84a03478b82cdd8883b0f3fd6ed84d6c959e553b887edcd"
               "6297dfa700000000fd0d53bb6215de4bb6f6f3d031a790287e45e9c1feb836c0a25ea71f5daaed4d"
               "99eb2ebebe3c432fec7d3abc4ccf30d3aaaf02a4ae8cb60b0300000038d856a40c67c3d4afa9c864"
               "9da90bd2fff2f25600000000000000000000000000000001955e1a13d1111b067acbce3e3bcdf382"
               "00154d12010000009edfa7a74c1c83c18e47935e8354846e34f0386a000000000000000000000000"
               "00000001ac26c7d41fd050bf8d85055bcfe3756c1e0f515601000000f57609453df7803357ae7998"
               "9870ccec3def0ad9000000000000000000000000000000019f05a16768cb3bc873b04d937a6ed8f7"
               "7c52a52d030000004e8e8bc17c01ac63eca0c1cfbb204132fb7213e4000000000000000000000000"
               "00000000accae11f8045a80f855ebf3b772eb2b1d03bc90503000000eb760e3f004a2efc8ffc96b8"
               "9b1bc8f415bd4e7700000000000000000000000000000000d149f074a378b881153ece68ade15cec"
               "6f0e9e6903000000ec2e2924348352d715cf9d411ea012e5307294b6000000000000000000000000"
               "00000000ccd2f50c30706cae3fdcc2f0ee3d5e267666c05303000000ffa8e89871fb9510b900b206"
               "1d0c334b819f2dd100000000000000000000000000000000095a3230fde69eec3af2e6d0bd68ab72"
               "81ae55f0030000000aa20624fbab244735d67c61283031667b2d74a1000000000000000000000000"
               "0000000000459582f4ef43c780908872746e39ef10613fc90200000016a31dc2e46a234558817151"
               "b38fc9c909cf8d7100000000000000000000000000000000ae17bb4515856092b4d9e89b676761b2"
               "57d6249b020000007dc7f17f666969e45c3baf7a119a65ee0b06fa9e000000000000000000000000"
               "00000000b314f695bd82e9ea8891ed0a3d1b91ca6e91b91501000000be5b534e0a6527f67485ab35"
               "aca0c7ee4197338500000000000000000000000000000000aefd4503189f7630248e501c9052c22b"
               "5d68265d010000009b7a559be3acf4fc36fa6b513cf09e8b99289462000000000000000000000000"
               "00000000b49185ad9b7d0070a36dd51323b2c542b56e03e0010000002f70249eefc67bce716c856e"
               "3973dc42a1003be9000000000000000000000000000000006176f78a19bb8df1804c122fce5078c1"
               "e5fe7d360100000066a3ae3939762df33a2d55060c78d551cbb110fd000000000000000000000000"
               "000000002c171ed15abbbe1cd911db7b56e8f3feeecc89f601000000d635edea8ffe423d01883918"
               "039249f398f9b37e000000000000000000000000000000001fb7c8307f06b4b29088f20d9ac676d5"
               "f90e54b501000000a779f37c30d2c5053c40ecae210aeb0934cb2a24000000000000000000000000"
               "00000000df48f333ef467092818aa77d6732b678bcd7be0700000000e45aaf61814f703b40125e6b"
               "af4648cbaaa37b86000000000000000000000000000000005ddb05f2a84e27c18a06e2c9cb29efdf"
               "50da49bf00000000d94beb259f9f0251becc987907879cca68fec7bb000000000000000000000000"
               "000000009402a4c2167721673f2b02b3256ead1fa349e1cc00000000b879a45176740744fcb6a035"
               "339d504c9726d80d000000000000000000000000000000009518862bc9a89192c1c8be55281a59d1"
               "bae87d60000000005d31e5b2de252167c1c91b3a36ba0c700ee78477000000000000000000000000"
               "000000006ad0143a0554efb46b382ab0404cdf02ebfdcec30000000067a982be8a934f852cc3d4d8"
               "2bc0ec7303f99f8f00000000000000000000000000000000901f55f960c55c22f32099a8020bea2a"
               "a2f56808092069affaa100fdfdd68d34be184524a6bdc8789cf85178000000000000000000000000"
               "00000000020ffdb0e612098610e52bb2a16a4008aefd545b020000007ced4f8b362956cd46646a0e"
               "222160e5f769bb2900000000000000000000000000000000a19da86c64fefab2548759d313a5b92d"
               "f05d7308020000009d82c856ba942455050f63f8282f3464443cacf5000000000000000000000000"
               "0000000069d9942f460bcea75481f25e307d0de99a6ce5d900000000a6a5ee19d6f63fe9cbdd01f7"
               "246f13b2050424a200000000000000000000000000000000ffe9d6812231bb02f922259b173c333c"
               "5b1aea3401000000c7c3523f76cf1ce34ca17a9a32f3f0f218424e48000000000000000000000000"
               "00000002e6fbf952902383028e3b47f2111d891d17a4763102000000f9119c40b468b66331bca67a"
               "034f43340d01683c00000000000000000000ffffb24a5be9b10123e6e4f15ecd1dff045298cfee06"
               "536c75bb01000000720da9e07ac998b5690807d52617369ee1af4ca500000000000000000000ffff"
               "47d7b351a36b178aabc78a4a0d80684ee5dbf45bb0916e5d030000004a503a712350acbd48411f0d"
               "c15d2f0f49dad345599706954d2471f00d3c723b91adb0da7c4aa7e7eb5a15bcde015fb98b841fd8"
               "ba8110fb03000000904f288262e6ea77a22fa5f863eaeefa701d120523bd98f29b098b43cd68be6e"
               "3f81268193fd637e585287dc6ca972a2cfb18b2b3cae864b0200000091921681c2162b9bfa40546c"
               "db544e44df2d7c2790d3119a051bb2ee8192ac0cfa3abc1ea0ab3e7d75a2f42b50c6a36340132378"
               "8c3b371502000000710c030690f5f18ea125dbf7d7e93bd65c1fa56dfdcfc1155f236c8b9c79a620"
               "5f660bbf024b03ff0a8e27c405e6424457393c6fdac12ebd01000000667224dae775e5ccd141aca2"
               "ff0f576767d3648102b61886b62f22ca33478e1f891715df7fc6a902edae579e2e10c7f7a22ba034"
               "abf85f0c0100000008d33a2ea67776d7f88d69c8c7e3b2d3c93ef054e93f8120abb42316c533d9c9"
               "4d88189c471a1ff2f0ce3ff66e782110125ae2edc7a4c65601000000cd625009a40aeb62a42b6a62"
               "548e3c38b96c20022753c5fbfaf1809becd2506315a6da29b2e94d3ab51fe0e9af98b180a36035fb"
               "daae7d6300000000c0982b283aa9986700b2a2b3ed257b8b0489f48f053ec8cac72105b327335a25"
               "a364d1015ffac03089f45539e1b0178462156cd66855676c00000000017c9148da5892bb4951c3a7"
               "ed55689d3391ce7d3fd48469845f0c233dbdd2a97835df1f1782dee88487fd0db5971b46b7a350f9"
               "cdb3455c00000000c66af76e80f062ea1a7e0b7be218d067530e1b0487b8c3b99f2b8a1a8982c42f"
               "53700a3437c5156e072b2f2fb337c9cfe07c34ddc896c9a7000000000a5f6abd850b06e3d9662795"
               "ce2cc1cee06302aba042aaa218dc091e9aa1477f6fdc9830d7fbc95829a8838314dff34d24c33221"
               "98c39e7c00000000efc57ff447036b9551adcb22fd50793f797a3c7dadd1c86e759d0c90bc512e13"
               "7dcef5e4a27985bd8d1e69c83dc21056b973972c7625ca4a00000000e682f80f94315c45ef817264"
               "c89a736ed55ed637b077ddad3108be69f9b97d05c917ad6b10e693bb6e26f2ba90c8e909e85e20e5"
               "9c88b02a0300000004b0595daf37deb499996bfb667f072dec1e5d9cdc8a11f4409bcfb3c167090e"
               "99d90a8543961b2ccd47724a3c460ba85183f4c5a7afe28302000000d05ff720b16c73761a3fcb67"
               "5219061ab4c5c79489b2cc6a883c146972decb8b5adac8f5e6d66df46ea139107754dee62c36d2fc"
               "e36f90d401000000fd41fe47684b370b6ec6584d64496089570968ead4d1ae91c819bb068196d599"
               "efde3246e43f5e7945aaf95e2ffa3a11b9ef1b214d4647f5000000000f88e3759a08e7a56663861e"
               "ea1bf42ccd3c72f2ad063857ca82ac5180101be4f85cef468ea086ea9aaafdc388811ec787bc45db"
               "0422ae3f03000000c43bd794c697895e5bfe47c6f53a54e01b0c1d89fecd94d0e02d2ec587fc3300"
               "03781b0f294a2b73c4421398f4de67e9cee64b38bc51e540030000006c3d048a92d3adc69a84eb47"
               "622400207799416afef0a086fbd7e2f7dea0077ae9c0c0d9c386e9c6e6a2cbfa10ee58bdc7518360"
               "36674cde0200000054cfe8f42bf0e9381ba2c4396de60f032bc7f34dfe959871c0d4c0d4eb720c4a"
               "e3c9472e5f2da5d9c5cfd9f2343b21362c19a092b2cd3dbd01000000e958e48d2ab8b0313e7f8933"
               "e315130fa9a84c82feb83f6e70b1646d8026e9f1704f1b16286ba2dabc7ef0820c91ed33ef60a8b5"
               "bcfe97e1000000007ad742d3d7320a4f880cf47f5dd0cf69cb22840ffeb3fe7749509cb6752b2cee"
               "30b7e7736a0afc9879ea40e69710fc9f6e8e99cd69121aec010000000fcc00ac2daa755e5292cd32"
               "dc096cd5d8a4c5cffe91ee1cfcc2056cc1ff8e51bbce426cfa4b861cc78592be7b14e7ba9c15acb8"
               "b83579b80300000072437f9b6245de39ec9e71ee4b951507beb42b34000000000000000000000000"
               "00000001d639272e4a46eadfbd2146bf8cfdb205b3980deb020000006c1de913df1424ce3ee1d76f"
               "c1ea76e98c9dfc7800000000000000000000000000000001e44ea74b4f2b83f9b3bee14d861a4c9e"
               "cf844ef501000000cd743f59bd14c89b5cfd5ce6e82e7854152f2b70000000000000000000000000"
               "0000000127e19f254ac9588319558041fc62ed561dce2f83020000003a3efc240b9977e166bee737"
               "fe73670c439a644c000000000000000000000000000000015e0dfe491d1ba96742c7b5e02b227122"
               "2af145480300000004265f6c72923e22594f3f79e208ed2e2ebb0771000000000000000000000000"
               "0000000039dd8f88152a58454d9ca9d20f45dfa774993ade03000000e62112898dab2dade2ab2fc9"
               "c56a7c86be5f962200000000000000000000000000000000bdd06352cb2c354434819f4b248eb2b8"
               "922b6cb8030000001d5c302df59dd32a677e5a3af4fe297f608df061000000000000000000000000"
               "000000008ae21e371051852c972ea7954079884a9f3c2c8803000000f51f44e644d7cf1d06b2b115"
               "d882549e62c12fba000000000000000000000000000000004fc812bd2f8a59d96d064126666befbb"
               "dc335c8b030000000a3c8e7c91bf821c4b09cee3c37ff4283a631480000000000000000000000000"
               "000000005588456e4ead7cbda620a3abae816e34e3ff1a5f03000000b4425486c619147eb0216050"
               "ed7afd741024e83600000000000000000000000000000000f493472201e48d163106cc397446a33f"
               "f257b044030000006a4c619f9037d7a754655354c47cf0f551e96770000000000000000000000000"
               "0000000050b8d10ab700cc3a7cf51be0403b654bbc74179403000000438a72e12ae0436a2495a609"
               "675344f7e2e3a5eb0000000000000000000000000000000061eda239d9d083c3bf085387046ef8a3"
               "4153e174020000004d89c0bb5408c1b7d17fb084d9e1825fa638e1af000000000000000000000000"
               "000000006e08cb887464b9344ec3127c750fabdd6c0fc09c02000000809829af4a9df58dbfef186d"
               "416f3a1ef170d10f0000000000000000000000000000000087780281d47a32f2235376239daeaacb"
               "74e7860402000000cd7db68b9ae586dacdb4070c50320427c4dd3d03000000000000000000000000"
               "00000000d538d34574c038404923e75d0e09e2fca9a89f8701000000fcdf6d9be94030b34774d1d7"
               "dddedd9899f0f62700000000000000000000000000000000848518c4e3f6cbf25e5e1b990fc46767"
               "fd338f35010000006e8cc34573654ea6624f138ef9531cd9367a02e4000000000000000000000000"
               "00000000da40d88d40a6d75bc404156225b7eede2cb749e2010000000eb4f73e75039fcf251b32fc"
               "79685b05ddd3aa9b000000000000000000000000000000000d58fbcc58fc4c2fd0d44ff1e51c3515"
               "6aae660b01000000fc1fb23d24438387def0f4c6544e4b275d9b7146000000000000000000000000"
               "00000000b883efebc09dd9d61966b7ae7412041db7f0318a01000000061db3dd7fde25654a4059d5"
               "65dbc8a91e3b445700000000000000000000000000000000c1b5aad487c192f08bd7a09bdd214443"
               "61c2f5d200000000b809d259e499db7dc8f1853bdcb0e4bc0e2b00b6000000000000000000000000"
               "000000005e7fa0f02f2f3313d8469d09a92409c0b4d54acb00000000a417f3da01d99dae5f190096"
               "cc582cabd5ddd15a00000000000000000000000000000000fdb3d117d76b0de5416f95e7bb75d72f"
               "59747cf200000000ab2dadc5a39411fd4ff1116d478987316a553fc2000000000000000000000000"
               "000000000819e3b10db116431ec6f7691539ce41b95c593100000000dbe9962069e66142e2275334"
               "4fda8a3e0b841cf7000000000000000000000000000000008c54dda9ac3bb1b1d43e6505621b9a7f"
               "fc2b445700000000496ad01bf007eacb0a28aec868282510b60291ea000000000000000000000000"
               "000000005b29a197b7b3cceaf5f1bb12c535256a0436242c03000000ee3fbc164632d4f28aa28c08"
               "f80dd50c6712dfb400000000000000000000000000000000078a806d329c9b008bbfc9723107f3f5"
               "9a1b163a030000000e2f4f911a0dd8c052ed6b13e2815a1a37a52bdd000000000000000000000000"
               "00000000bd99fcf72909ac9e7a55299e9bb4fd53fc1519de010000002545666937c22a3b6e9686dc"
               "c405cbee5016c252000000000000000000000000000000006e4c699341b95f41d9c1e67743efb54e"
               "d7ac5f9901000000822a272bec4501a1e27acfee7a8588ffd5a06cae000000000000000000000000"
               "0000000077a47579dda0b6ead1e1b34901eaedd54f1b134803000000449a774929e86716ec852d59"
               "f3d17232edd86ad6000000000000000000000000000000027dba1ee7e143fd52599364e13468f80f"
               "40b26f6603000000badfad0fe8fa8f3c1aad2a82530b7447d9c2f401000000000000000000000000"
               "000000028147507e1cd59ea1ae6da48b1eba6d16dedea2030100000002a1f8e6f5657f3f9e3eb807"
               "cbad76451055edb800000000000000000000000000000002d9279fb2b8fcbac6abea74f7a6df7979"
               "672d2fa501000000e276c5661a64192db44ce7af5eb888e9eb37bb04000000000000000000000000"
               "00000002641e447514ca565fb9b68c08a5e4351e9f3c39f201000000de745cb25851429b3bbfb501"
               "68dfd04edf6b35420000000000000000000000000000000218f93e742d08f0550b55726f2292362e"
               "70ccc56700000000a4c73cf5ffa4ffc8a4bab14874afdf54e6aae816000000000000000000000000"
               "0000000268baf76ab08940f6fc3bbdc7f6090f75f6989d2d000000006ff7add5df2c93e05459507b"
               "5d8c6a0f466554d200000000000000000000ffff1785d3ffdbd9a617857ae8126b028c0e3e295354"),
    };
    const int   TEST_DATA_I      = GPOINTER_TO_INT(test_data);
    const int   addr_family      = (TEST_DATA_I == 0 ? AF_INET : AF_INET6);
    const int   IPV6_PREFER_TEMP = (TEST_DATA_I == 2);
    const guint N_ADDRESSES      = 100;
    const gsize ELM_SIZE =
        addr_family == AF_INET ? sizeof(NMPlatformIP4Address) : sizeof(NMPlatformIP6Address);
    const gboolean DO_REGENERATE = FALSE;
    const gboolean PRINT_RESULT  = DO_REGENERATE;
    const gboolean CHECK_RESULT  = !DO_REGENERATE;
    gs_free guint8 *addresses    = NULL;
    gs_free guint64 *rand_map    = NULL;
    gsize            i, j;

#if !defined(__amd64__)
    /* The test generates a random array of NMPlatformIPXAddress (by crudely randomizing the memory,
     * not the structures themself) and then compares the sorted result with the expected output.
     * The sole purpose is to ensure that the sorting order stays stable.
     *
     * This only works on an architecture for which the test was made, otherwise
     * the expected data does not match (due to different layout of the structures
     * in memory).
     *
     * That's fine. Skip the test. */
    g_test_skip("skip test on non-amd64 architecture");
    return;
#endif

    /*
     * First we create a list of addresses filled with (stable) random bytes.
     * We tweak some fields explicitly (stable randomly), so that we cover all
     * relevant cases.
     *
     * Then we sort the list of addresses, and compare that the result is
     * as our EXPECTED_BUFFER.
     */

    addresses = g_malloc(ELM_SIZE * N_ADDRESSES);
    rand_map  = g_malloc(sizeof(rand_map[0]) * N_ADDRESSES);
    nmtst_stable_rand(258829693, addresses, ELM_SIZE * N_ADDRESSES);
    nmtst_stable_rand(710086081, rand_map, sizeof(rand_map[0]) * N_ADDRESSES);

    for (i = 0; i < N_ADDRESSES; i++) {
        NMPlatformIPXAddress *a = (gpointer)(&addresses[i * ELM_SIZE]);
        guint64               r = rand_map[i];
        struct in6_addr *     a6;

#define CONSUME_BITS(r, nbits)                        \
    ({                                                \
        guint64   _r     = (r);                       \
        const int _nbits = (nbits);                   \
                                                      \
        r >>= (_nbits);                               \
        (_r & (((((guint64) 1u) << (_nbits)) - 1u))); \
    })

        if (addr_family == AF_INET) {
            if (CONSUME_BITS(r, 1)) {
                /* randomly create a link-local address or not. */
                g_assert((NM_IPV4LL_NETWORK & ~NM_IPV4LL_NETMASK) == 0);
                a->a4.address = (a->a4.address & ~NM_IPV4LL_NETMASK) | NM_IPV4LL_NETWORK;
            }
        } else {
            a6 = &a->a6.address;
            switch (CONSUME_BITS(r, 4)) {
            case 0:
                a6->s6_addr32[0] = 0;
                a6->s6_addr32[1] = 0;
                a6->s6_addr32[2] = htonl(0xffff);
                g_assert(IN6_IS_ADDR_V4MAPPED(a6));
                break;
            case 1:
                a6->s6_addr32[0] = 0;
                a6->s6_addr32[1] = 0;
                a6->s6_addr32[2] = 0;
                a6->s6_addr32[3] = htonl(2);
                g_assert(IN6_IS_ADDR_V4COMPAT(a6));
                break;
            case 2:
                a6->s6_addr32[0] = 0;
                a6->s6_addr32[1] = 0;
                a6->s6_addr32[2] = 0;
                a6->s6_addr32[3] = 0;
                g_assert(IN6_IS_ADDR_UNSPECIFIED(a6));
                break;
            case 3:
                a6->s6_addr32[0] = 0;
                a6->s6_addr32[1] = 0;
                a6->s6_addr32[2] = 0;
                a6->s6_addr32[3] = htonl(1);
                g_assert(IN6_IS_ADDR_LOOPBACK(a6));
                break;
            case 4:
                a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfe800000);
                g_assert(IN6_IS_ADDR_LINKLOCAL(a6));
                break;
            case 6:
                a6->s6_addr32[0] = (a6->s6_addr32[0] & ~htonl(0xffc00000)) | htonl(0xfec00000);
                g_assert(IN6_IS_ADDR_SITELOCAL(a6));
                break;
            case 7:
            case 8:
            case 9:
            case 10:
                break;
            default:
                memset(a6, 0, sizeof(*a6));
                break;
            }
        }

        if (CONSUME_BITS(r, 5) != 0) {
            /* randomly make addr-source the same (so that several addresses compare
             * equal). */
            a->a4.addr_source = CONSUME_BITS(r, 2);
        }

        if (addr_family == AF_INET) {
            if (CONSUME_BITS(r, 1)) {
                /* randomly make the label empty or not. */
                a->a4.label[0] = '\0';
            }
        }
        if (addr_family == AF_INET) {
            if (CONSUME_BITS(r, 2) != 0) {
                /* randomly make the label empty or not. */
                a->a4.plen = CONSUME_BITS(r, 2);
            }
        }
        if (addr_family == AF_INET) {
            if (CONSUME_BITS(r, 1)) {
                a->a4.address = (a->a4.address & ~0xFFFFFFu) | (CONSUME_BITS(r, 2) << 24);
            }
        }
    }

    g_qsort_with_data(addresses,
                      N_ADDRESSES,
                      ELM_SIZE,
                      _address_pretty_sort_cmp,
                      (gpointer) test_data);

    for (i = 0; i < N_ADDRESSES; i++) {
        const NMPlatformIPXAddress *a = (gconstpointer)(&addresses[i * ELM_SIZE]);

        for (j = i + 1; j < N_ADDRESSES; j++) {
            const NMPlatformIPXAddress *b = (gconstpointer)(&addresses[j * ELM_SIZE]);
            int                         c1;
            int                         c2;

            if (addr_family == AF_INET) {
                c1 = nm_platform_ip4_address_pretty_sort_cmp(&a->a4, &b->a4);
                c2 = nm_platform_ip4_address_pretty_sort_cmp(&b->a4, &a->a4);
            } else {
                c1 = nm_platform_ip6_address_pretty_sort_cmp(&a->a6, &b->a6, IPV6_PREFER_TEMP);
                c2 = nm_platform_ip6_address_pretty_sort_cmp(&b->a6, &a->a6, IPV6_PREFER_TEMP);
            }

            g_assert_cmpint(c1, >=, -1);
            g_assert_cmpint(c1, <=, 1);
            g_assert_cmpint(c1, ==, -c2);
        }
    }

    if (PRINT_RESULT) {
        g_print("\n        [%d] = (", TEST_DATA_I);
        for (i = 0; i < ELM_SIZE * N_ADDRESSES;) {
            if (i > 0)
                g_print("\n               ");
            g_print("\"");
            for (j = 0; j < 40 && i < ELM_SIZE * N_ADDRESSES; j++, i++)
                g_print("%02x", addresses[i]);
            g_print("\"");
        }
        g_print("),\n");
        return;
    }

    if (CHECK_RESULT) {
        gs_free guint8 *bin_arr = NULL;
        gsize           bin_len;

        bin_arr = nm_utils_hexstr2bin_alloc(EXPECTED_BUFFER[TEST_DATA_I],
                                            FALSE,
                                            FALSE,
                                            NULL,
                                            0,
                                            &bin_len);

        if (bin_len != ELM_SIZE * N_ADDRESSES || memcmp(addresses, bin_arr, bin_len) != 0) {
            char *addresses_str = nm_utils_bin2hexstr(addresses, ELM_SIZE * N_ADDRESSES, -1);

            g_error(">>> test_platform_ip_address_pretty_sort_cmp() will fail:\n"
                    ">>> addresses[%zu]: %s\n"
                    ">>> expected [%zu]: %s\n",
                    ELM_SIZE * N_ADDRESSES,
                    addresses_str,
                    bin_len,
                    EXPECTED_BUFFER[TEST_DATA_I]);
        }

        g_assert_cmpmem(addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len);
    }
}

/*****************************************************************************/

NMTST_DEFINE();

int
main(int argc, char **argv)
{
    nmtst_init_assert_logging(&argc, &argv, "WARN", "DEFAULT");

    g_test_add_func("/general/init_linux_platform", test_init_linux_platform);
    g_test_add_func("/general/link_get_all", test_link_get_all);
    g_test_add_func("/general/nm_platform_link_flags2str", test_nm_platform_link_flags2str);
    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/4",
                         GINT_TO_POINTER(0),
                         test_platform_ip_address_pretty_sort_cmp);
    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/1",
                         GINT_TO_POINTER(1),
                         test_platform_ip_address_pretty_sort_cmp);
    g_test_add_data_func("/general/platform_ip_address_pretty_sort_cmp/6/2",
                         GINT_TO_POINTER(2),
                         test_platform_ip_address_pretty_sort_cmp);

    return g_test_run();
}
